package higo

import (
	"github.com/dunpju/higo-router/router"
	"github.com/dunpju/higo-throw/exception"
	"github.com/gin-gonic/gin"
	"net/http"
	"reflect"
	"regexp"
	"runtime"
	"strings"
)

//路由容器
var RouterContainer *RouterCollect

type RouterCollect struct {
}

func NewRouterCollect() *RouterCollect {
	return &RouterCollect{}
}

// 获取路由
func (this RouterCollect) Get(serve, method, relativePath string) *router.Route {
	node, err := router.GetRoutes(serve).Search(method, relativePath)
	if err != nil {
		exception.Throw(exception.Message(relativePath+" Undefined route"), exception.Code(0))
	}
	return node.Route
}

//添加路由
func (this *Higo) AddRoute(httpMethod string, relativePath string, handler interface{}, attributes ...*router.RouteAttribute) *Higo {
	funcForPCName := runtime.FuncForPC(reflect.ValueOf(handler).Pointer()).Name()
	structFuncRegexp := regexp.MustCompile(`\.\(.*\)\..*-fm$`)
	if structFuncRegexp.MatchString(funcForPCName) {
		structNameRegexp := regexp.MustCompile(`\.\(.*\)\.`)
		structName := structNameRegexp.FindString(funcForPCName)
		structName = strings.Replace(structName, ".(*", "", 1)
		structName = strings.Replace(structName, ").", "", 1)
		methodRegexp := regexp.MustCompile(`\)\..*\-fm`)
		method := methodRegexp.FindString(funcForPCName)
		method = strings.Replace(method, ").", "", 1)
		method = strings.Replace(method, "-fm", "", 1)
		structPath := structFuncRegexp.ReplaceAllString(funcForPCName, "")
		diname := structPath + "/" + structName
		icl := Di(diname)
		if nil != icl {
			router.AddRoute(httpMethod, relativePath, newDispatch(icl, method).Convert(handler), attributes...)
		} else {
			router.AddRoute(httpMethod, relativePath, handler, attributes...)
		}
	} else { // 非struct Method
		//获取handler所在文件名称
		//handlerFile, _ := runtime.FuncForPC(reflect.ValueOf(handler).Pointer()).FileLine(reflect.ValueOf(handler).Pointer()) // go 1.18 struct Method return <autogenerated>
		router.AddRoute(httpMethod, relativePath, handler, attributes...)
	}
	return this
}

//添加路由组
func (this *Higo) AddGroup(prefix string, callable func(), attributes ...*router.RouteAttribute) *Higo {
	router.AddGroup(prefix, callable, attributes...)
	return this
}

//websocket路由
func (this *Higo) Ws(relativePath string, handler interface{}, attributes ...*router.RouteAttribute) *Higo {
	this.AddRoute(router.WEBSOCKET, relativePath, handler, attributes...)
	return this
}

func (this *Higo) Get(relativePath string, handler interface{}, attributes ...*router.RouteAttribute) *Higo {
	this.AddRoute(router.GET, relativePath, handler, attributes...)
	return this
}

func (this *Higo) Post(relativePath string, handler interface{}, attributes ...*router.RouteAttribute) *Higo {
	this.AddRoute(router.POST, relativePath, handler, attributes...)
	return this
}

func (this *Higo) Put(relativePath string, handler interface{}, attributes ...*router.RouteAttribute) *Higo {
	this.AddRoute(router.PUT, relativePath, handler, attributes...)
	return this
}

func (this *Higo) Delete(relativePath string, handler interface{}, attributes ...*router.RouteAttribute) *Higo {
	this.AddRoute(router.DELETE, relativePath, handler, attributes...)
	return this
}

func (this *Higo) Patch(relativePath string, handler interface{}, attributes ...*router.RouteAttribute) *Higo {
	this.AddRoute(router.PATCH, relativePath, handler, attributes...)
	return this
}

func (this *Higo) Head(relativePath string, handler interface{}, attributes ...*router.RouteAttribute) *Higo {
	this.AddRoute(router.HEAD, relativePath, handler, attributes...)
	return this
}

func (this *Higo) Flag(value string) *router.RouteAttribute {
	return router.NewRouteAttribute(router.RouteFlag, value)
}

func (this *Higo) FrontPath(value string) *router.RouteAttribute {
	return router.NewRouteAttribute(router.RouteFrontpath, value)
}

func (this *Higo) IsStatic(value bool) *router.RouteAttribute {
	return router.NewRouteAttribute(router.RouteIsStatic, value)
}

//描述
func (this *Higo) Desc(value string) *router.RouteAttribute {
	return router.NewRouteAttribute(router.RouteDesc, value)
}

//单路由中间件
func (this *Higo) Middle(handlers ...gin.HandlerFunc) *router.RouteAttribute {
	values := make([]interface{}, 0)
	for _, handler := range handlers {
		values = append(values, handler)
	}
	return router.NewRouteAttribute(router.RouteMiddleware, values...)
}

//组中间件
func (this *Higo) GroupMiddle(handlers ...gin.HandlerFunc) *router.RouteAttribute {
	values := make([]interface{}, 0)
	for _, handler := range handlers {
		values = append(values, handler)
	}
	return router.NewRouteAttribute(router.RouteGroupMiddle, values...)
}

func (this *Higo) SetServe(value interface{}) *router.RouteAttribute {
	return router.NewRouteAttribute(router.RouteServe, value)
}

func (this *Higo) SetHeader(value http.Header) *router.RouteAttribute {
	return router.NewRouteAttribute(router.RouteHeader, value)
}
